
#include "openMVG/image/image_container.hpp"
#include "openMVG/image/image_converter.hpp"
#include "openMVG/image/pixel_types.hpp"
#include "openMVG/image/image_io.hpp"
#include "openMVG/image/image_drawing.hpp"

// #include "openMVG/sfm/sfm.hpp"
#include "openMVG/sfm/sfm_data.hpp"
#include "openMVG/sfm/sfm_data_io.hpp"

#include "openMVG/features/akaze/image_describer_akaze_io.hpp"
#include "openMVG/features/regions_factory_io.hpp"
#include "openMVG/features/sift/SIFT_Anatomy_Image_Describer_io.hpp"
#include "openMVG/features/feature.hpp"
#include "openMVG/features/sift/SIFT_Anatomy_Image_Describer_io.hpp"
#include "openMVG/features/regions_factory_io.hpp"
#include "openMVG/features/svg_features.hpp"
// #include "openMVG/features/image_describer.hpp"

#include <cereal/cereal.hpp>
#include <cereal/details/helpers.hpp>
// #include <cereal/archives/json.hpp>
// #include <cereal/archives/xml.hpp>
// #include <cereal/archives/portable_binary.hpp>
#include "openMVG/system/timer.hpp"

#include "openMVG/third_party/stlplus3/filesystemSimplified/file_system.hpp"
#include "openMVG/third_party/vectorGraphics/svgDrawer.hpp"

#include <cstdio>
#include <iostream>
#include <string>
using namespace openMVG;
using namespace openMVG::image;
using namespace openMVG::sfm;
using namespace std;
using namespace openMVG::features;
int main(int, char **)
{
  const string data_root = "/root/code/3dRe/data/projectData/test1/";
  // Image<unsigned char> image(1080,1080);
  // image.fill(0);
  // int row = 2;
  // int column = 4;
  // image(row, column) = 127;
  // int radius = 100;
  // int x = 500, y = 500;
  // DrawCircle(x, y, radius, (unsigned char)255, &image);
  // WriteImage("test_write_png.png",image);
  // Image<RGBColor> image;
  // const string data_root="/root/code/3dRe/data/projectData/test1/";
  // ReadImage("/root/code/3dRe/data/projectData/test1/VID_20210614_141105_00_006_000001.jpg",&image);
  // ImageHeader imgHeader;
  // ReadImageHeader("/root/code/3dRe/data/projectData/test1/VID_20210614_141105_00_006_000001.jpg",&imgHeader);
  // cout<<"image width:"<<imgHeader.width<<endl<<"image hegiht:"<<imgHeader.height<<endl;
  SfM_Data sfm_data;
  sfm_data.s_root_path = data_root;
  Views &views = sfm_data.views;

  vector<string> vImgPath = stlplus::folder_files(data_root);
  // vector<string> vImgPath = folder_files(data_root);
  // if(!stlplus::is_file(data_root))
  // cout << "hi"<<endl;
  sort(vImgPath.begin(), vImgPath.end());
  int id = 0;
  for (auto ite = vImgPath.begin(); ite != vImgPath.end(); ++ite, ++id)
  {
    ImageHeader imgHeader;
    string data_path = data_root + *ite;
    ReadImageHeader(data_path.c_str(), &imgHeader);
    cout << "image width:" << imgHeader.width << endl
         << "image hegiht:" << imgHeader.height << endl;

    View v(*ite, views.size(), views.size(), views.size(), imgHeader.width, imgHeader.height);
    views[v.id_view] = make_shared<View>(v);
  }

  string sSaveDir = "/root/code/3dRe/data/output/tempdata";
  string sOutDir = "/root/code/3dRe/data/output/tempdata/features";
  // Create save dir
  if (!stlplus::folder_exists(sOutDir))
  {
    if (!stlplus::folder_create(sOutDir))
    {
      std::cerr << "Cannot create output directory" << std::endl;
      return EXIT_FAILURE;
    }
  }

  // save test
  //   if (!Save(
  //           sfm_data,
  //           stlplus::create_filespec(sSaveDir, "sfm_data.json").c_str(),
  //           ESfM_Data(VIEWS | INTRINSICS)))
  //   {
  //       cout << "error_save" << endl;
  //   }

  // load test
  // SfM_Data sfm_data_input;
  // if (!Load(sfm_data_input, sSaveDir, ESfM_Data(VIEWS))) {
  //   std::cerr << std::endl
  //     << "The input file \""<< sSaveDir<< "\" cannot be read" << std::endl;
  //   return EXIT_FAILURE;
  // }

  unique_ptr<Image_describer> image_describer;

  string sImageDescriber = stlplus::create_filespec(sOutDir, "image_describer", "json");

  std::map<IndexT, std::unique_ptr<features::Regions>> regions_perImage;
  image_describer.reset(new SIFT_Anatomy_Image_describer(SIFT_Anatomy_Image_describer::Params()));

  if (!image_describer)
  {
    std::cerr << "Cannot create the designed Image_describer"
              << "." << std::endl;
    return EXIT_FAILURE;
  }
  // std::ofstream stream(sImageDescriber.c_str());
  //       if (!stream.is_open())
  //         return EXIT_FAILURE;

  //       cereal::JSONOutputArchive archive(stream);
  //       archive(cereal::make_nvp("image_describer", image_describer));
  //       auto regionsType = image_describer->Allocate();
  //       archive(cereal::make_nvp("regions_type", regionsType));

  for (int i = 0; i < static_cast<int>(sfm_data.views.size()); ++i)
  {
    Views::const_iterator iterViews = sfm_data.views.begin();
    std::advance(iterViews, i);

    // create files to store matches
    const View *view = iterViews->second.get();
    const string sView_filename = stlplus::create_filespec(sfm_data.s_root_path, view->s_Img_path),
                 sFeat = stlplus::create_filespec(sOutDir, stlplus::basename_part(sView_filename), "feat"),
                 sDesc = stlplus::create_filespec(sOutDir, stlplus::basename_part(sView_filename), "desc");

    Image<unsigned char> tempimage;
    string image_path=sfm_data.s_root_path+view->s_Img_path;
    bool imageOk=ReadImage(image_path.c_str(), &tempimage);
    if (!imageOk)
    {
      cout << "can not find stored image" << endl;
    }
    Image<unsigned char> *mask = nullptr; // The mask is null by default
    auto regionsType = image_describer->Allocate();
    auto regions = image_describer->Describe(tempimage, regionsType);
    if (!(imageOk &&regions && image_describer->Save(regionsType.get(), sFeat, sDesc)))
    {
      std::cerr << "Cannot save regions for images " << std::endl
                << "Stopping feature extraction." << std::endl;
      continue;
    }
    else{
      // string filename=view->s_Img_path.substr(0,view->s_Img_path.size()-3)+"svg";
      string filename =stlplus::basename_part(view->s_Img_path)+".svg";
      string sSvgFilePath=sOutDir+"/svg";
      if(!stlplus::folder_exists(sSvgFilePath))
      {
        if(! stlplus::folder_create(sSvgFilePath))
        {
          cout<<"can not create svg save path!"<<endl;
          return EXIT_FAILURE;
        }
      }
      cout <<"*****"<<view->s_Img_path<<":finished"<<endl;
      cout<<regionsType->RegionCount()<< " #Features on image A" << std::endl;
      Features2SVG(image_path,{tempimage.Width(),tempimage.Height()},regionsType->GetRegionsPositions(),sSvgFilePath+"/"+filename);
    }


  }
  return 0;
}
